/**
 * @file	DataProcessing.h
 * @author  Thomas Fu <thomas.ks.fu@gmail.com>
 * @author	Ben Treweek <btreweek@gmail.com>
 * @version 0.0.1
 * @date	06/02/2011	
 *
 * @section License
 * This program is propety of Jyeah Jyeah Jyeah Jyeah Jyeah and may not be used 
 * by any individual for any purpose at any time without express permission from 
 * Mike Casey, Thomas Fu, Chris Hairfield, Kyle Lamson, Ben Treweek, or Cliff 
 * Warren.
 *
 * @brief 
 * This file contains the headers for data processing methods to be used for 
 * input and output data being passed to and from a neural network. 
 */

#ifndef _dataprocessing_h
#define _dataprocessing_h

#include <cstdlib>
#include <cstdio>

/** @def SCALE_MIN The minimum value in a given column after normalization */
#ifndef SACLE_MIN
#define SCALE_MIN 0.05
#else 
#error Redefinition of SCALE_MIN 
#endif

/** @def SCALE_MAX The maximum value in a given column after normalization */
#ifndef SACLE_MAX
#define SCALE_MAX 0.05
#else 
#error Redefinition of SCALE_MAX 
#endif

/**
 * Function that scales a two dimensional array of either floats or doubles
 * such that all of the values in each column are between SCALE_MIN and 
 * SCALE_MAX. This is achieved column-by-column by subtracting the minimum value
 * in each column from every value in that column, multilpying each value in 
 * that column by the multiplicative inverse of the largest value in that 
 * column, and finally by adding SCALE_MIN to each value in that column.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param rawData A two dimensional array of raw numerical data. Assumed to be 
 * rectangular
 *
 * @param normalizedData A two dimensional array containing the normalized 
 * version of the raw data (should have the same dimensions as rawData). Space 
 * for this data is allocated by NormalizeData.
 *
 * @param offsets A one dimensional array of numCols elements, such that each 
 * element of offsets is the minimum value in each column. Space for this array
 * is allocated in NormalizeData.
 *
 * @param scaleFactors A one dimensional array of numCols elements such that  
 * each element of scaleFactors corresponds to one divided by the largest value
 * in each column. Space for this array is allocated in NormalizeData.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 */
template <typename numType>
void NormalizeDataCols(numType **rawData, numType **normalizedData, 
									 numType *offsets, numType *scaleFactors, int numRows, 
									 int numCols);

/**
 * Function that scales a two dimensional array of either floats or doubles
 * such that all of the values in each row are between SCALE_MIN and 
 * SCALE_MAX. This is achieved row-by-row by subtracting the minimum value
 * in each row from every value in that row, multilpying each value in 
 * that row by the multiplicative inverse of the largest value in that 
 * row, and finally by adding SCALE_MIN to each value in that row.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param rawData A two dimensional array of raw numerical data. Assumed to be 
 * rectangular
 *
 * @param normalizedData A two dimensional array containing the normalized 
 * version of the raw data (should have the same dimensions as rawData). Space 
 * for this data is allocated by NormalizeData.
 *
 * @param offsets A one dimensional array of numRows elements, such that each 
 * element of offsets is the minimum value in each row. Space for this array
 * is allocated in NormalizeData.
 *
 * @param scaleFactors A one dimensional array of numRows elements such that  
 * each element of scaleFactors corresponds to one divided by the largest value
 * in each row. Space for this array is allocated in NormalizeData.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 */
template <typename numType>
void NormalizeDataRows(numType **rawData, numType **normalizedData, 
											 numType *offsets, numType *scaleFactors, int numRows, 
											 int numCols);

/**
 * Function that unscales a two normalized dimensional array of either floats or 
 * doubles, where all of the values in each column are between SCALE_MIN and 
 * SCALE_MAX, by inverting the process performed in NormalizeDataCols. 
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param normalizedData A two dimensional array containing the normalized 
 * version of the raw data (in the format produced by NormalizeDataCols). 
 *
 * @param unNormalizedData A two dimensional array of the inverted version of
 * the data contained in normalizedData. This should be such that it completely
 * inverts the process performed in NormalizeDataCols. Space for this array is 
 * allocated in UnNormalizeDataCols.
 *
 * @param offsets A one dimensional array of numCols elements, such that each 
 * element of offsets is the minimum value in each column. 
 *
 * @param scaleFactors A one dimensional array of numCols elements such that  
 * each element of scaleFactors corresponds to one divided by the largest value
 * in each column.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 */
template <typename numType>
void UnNormalizeDataCols(numType **normalizedData, numType **unNormalizedData, 
									 numType *offsets, numType *scaleFactors, int numRows, 
									 int numCols);

/**
 * Function that unscales a two normalized dimensional array of either floats or 
 * doubles, where all of the values in each row are between SCALE_MIN and 
 * SCALE_MAX, by inverting the process performed in NormalizeDataRows. 
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param normalizedData A two dimensional array containing the normalized 
 * version of the raw data (in the format produced by NormalizeDataRows). 
 *
 * @param unNormalizedData A two dimensional array of the inverted version of
 * the data contained in normalizedData. This should be such that it completely
 * inverts the process performed in NormalizeDataRows. Space for this array is 
 * allocated in UnNormalizeDataRows.
 *
 * @param offsets A one dimensional array of numRows elements, such that each 
 * element of offsets is the minimum value in each row. 
 *
 * @param scaleFactors A one dimensional array of numRows elements such that  
 * each element of scaleFactors corresponds to one divided by the largest value
 * in each row.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 */
template <typename numType>
void UnNormalizeDataRows(numType **normalizedData, numType **unNormalizedData, 
										 numType *offsets, numType *scaleFactors, int numRows, 
										 int numCols);

/**
 * Function that numerically computes the first derivative (up to a scaling 
 * factor) of the values contained in data and places the results in derivative. 
 * The derivative computations are O(h) or O(h^2) for speed and assume evenly 
 * spaced gridpoints. 
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A one dimensional array containing the numeric data to be 
 * differentiated. Space for this array will be allocated in this function.
 *
 * @param derivative A one dimensional array containing the numeric derivative
 * of the values contained in data. Derivatives are computed up to a scale 
 * factor since the spacing of the grid points is not necessarily known
 *
 * @param numElem An integer value specifying the number of elements in the 
 * data array.
 */
template <typename numType>
void ComputeFirstDerivative(numType *data, numType *derivative, int numElem);

/**
 * Function that numerically computes the second derivative (up to a scaling 
 * factor) of the values contained in data and places the results in derivative. 
 * The derivative computations are O(h) or  O(h^2) for speed and assume evenly 
 * spaced gridpoints. Calculated by a different method than just two successive
 * calculations of first derivatives in order to improve speed and accuracy.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A one dimensional array containing the numeric data to be 
 * differentiated. Space for this array will be allocated in this function.
 *
 * @param derivative A one dimensional array containing the numeric second
 * derivative of the values contained in data. Derivatives are computed up to a 
 * scale factor since the spacing of the grid points is not necessarily known
 *
 * @param numElem An integer value specifying the number of elements in the 
 * data array.
 */
template <typename numType>
void ComputeSecondDerivative(numType *data, numType *derivative, int numElem);

/**
 * Function that returns an array of integers corresponding to the indicies of 
 * the largest numToFind elements of the row of data specified by searchRow. The
 * elements of the returned array of ints should be in sorted order such that
 * the first element is the index of the largest element. If searchRow is out of 
 * bounds, this function will return NULL. If numToFind is greater than or
 * equal to the number of columns of data the returned array simply contains
 * the indices of all elements from largest to smallest.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A two dimensional array containing the numeric data to be 
 * searched. 
 *
 * @param searchRow The row of data to be searched for the largest values
 *
 * @param numToFind The number of largest elements to find. For instance, if
 * numToFind is five, then this function should return the indices of the five
 * largest elements.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 *
 * @return An array containing the indices of the largest elements in searchRow
 * sorted such that the first element of this array corresponds to the largest
 * element.
 */
template <typename numType>
int* FindLargestMembersInRow(numType **data, int searchRow, int numToFind,
															int numRows, int numCols);

/**
 * Function that returns an array of integers corresponding to the indicies of 
 * the smallest numToFind elements of the row of data specified by searchRow. 
 * The elements of the returned array of ints should be in sorted order such 
 * that the first element is the index of the smallest element. If searchRow is  
 * out of bounds, this function will return NULL. If numToFind is greater than 
 * or equal to the number of columns of data the returned array simply contains
 * the indices of all elements from smallest to largest.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A two dimensional array containing the numeric data to be 
 * searched. 
 *
 * @param searchRow The row of data to be searched for the smallest values
 *
 * @param numToFind The number of smallest elements to find. For instance, if
 * numToFind is five, then this function should return the indices of the five
 * smallest elements.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 *
 * @return An array containing the indices of the smallest elements in searchRow
 * sorted such that the first element of this array corresponds to the smallest
 * element.
 */
template <typename numType>
int* FindSmallestMembersInRow(numType **data, int searchRow, int numToFind,
															int numRows, int numCols);

/**
 * Function that returns an array of integers corresponding to the indicies of 
 * the largest numToFind elements of the column of data specified by searchCol. 
 * The elements of the returned array of ints should be in sorted order such 
 * that the first element is the index of the largest element. If searchCol is
 * out of bounds, this function will return NULL. If numToFind is greater than 
 * or equal to the number of rows of data the returned array simply contains
 * the indices of all elements from largest to smallest.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A two dimensional array containing the numeric data to be 
 * searched. 
 *
 * @param searchCol The column of data to be searched for the largest values
 *
 * @param numToFind The number of largest elements to find. For instance, if
 * numToFind is five, then this function should return the indices of the five
 * largest elements.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 *
 * @return An array containing the indices of the largest elements in searchCol
 * sorted such that the first element of this array corresponds to the largest
 * element.
 */
template <typename numType>
int* FindLargestMembersInCol(numType **data, int searchCol, int numToFind,
															int numRows, int numCols);

/**
 * Function that returns an array of integers corresponding to the indicies of 
 * the smallest numToFind elements of the column of data specified by searchCol. 
 * The elements of the returned array of ints should be in sorted order such 
 * that the first element is the index of the smallest element. If searchCol is
 * out of bounds, this function will return NULL. If numToFind is greater than 
 * or equal to the number of rows of data the returned array simply contains
 * the indices of all elements from smallest to largest.
 *
 * @tparam numType The data type used to represent the numerical data. In most
 * use cases will either be a float or a double. Templatized here for the sake
 * of being generic.
 *
 * @param data A two dimensional array containing the numeric data to be 
 * searched. 
 *
 * @param searchCol The column of data to be searched for the smallest values
 *
 * @param numToFind The number of smallest elements to find. For instance, if
 * numToFind is five, then this function should return the indices of the five
 * smallest elements.
 *
 * @param numRows The number of rows in rawData
 *
 * @param numCols The number of columns in rawData
 *
 * @return An array containing the indices of the smallest elements in searchCol
 * sorted such that the first element of this array corresponds to the smallest
 * element.
 */
template <typename numType>
int* FindSmallestMembersInCol(numType **data, int searchCol, int numToFind,
															int numRows, int numCols);

#endif